home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / icon / packages.lha / packages / atari / ats.arc / TESTS.ARC / GC2.ICN < prev    next >
Text File  |  1990-03-28  |  5KB  |  223 lines

  1. global defs, ifile, in, limit, tswitch, prompt
  2.  
  3. record nonterm(name)
  4. record charset(chars)
  5. record query(name)
  6.  
  7. procedure main(x)
  8.    local line, plist
  9.    plist := [define,generate,grammar,source,comment,prompter,error]
  10.    defs := table()
  11.    defs["lb"] := [["<"]]
  12.    defs["rb"] := [[">"]]
  13.    defs["vb"] := [["|"]]
  14.    defs["nl"] := [["\n"]]
  15.    defs[""] := [[""]]
  16.    defs["&lcase"] := [[charset(&lcase)]]
  17.    defs["&ucase"] := [[charset(&ucase)]]
  18.    defs["&digit"] := [[charset('0123456789')]]
  19.    i := 0
  20.    while i < *x do {
  21.       s := x[i +:= 1] | break
  22.       case s of {
  23.          "-t":   tswitch := 1
  24.          "-l":   limit := integer(x[i +:= 1]) | stop("usage: [-t] [-l n]")
  25.          default:   stop("usage: [-t] [-l n]")
  26.          }
  27.       }
  28.    ifile := [&input]
  29.    prompt := ""
  30.    test := ["<a>::=1|2|3","<a>10","->","<b>::=<a>|<a><a>|<b><b>","<b>5",
  31.       "<c>::=<b><b><b>","<c>100","<b>100"]
  32.    every line := !test do {
  33.       (!plist)(line)
  34.       collect()
  35.       every write(&collections)
  36.       write("----------")
  37.       }
  38. end
  39.  
  40. procedure comment(line)
  41.    if line[1] == "#" then return
  42. end
  43.  
  44. procedure define(line)
  45.    return line ?
  46.       defs[(="<",tab(find(">::=")))] := (move(4),alts(tab(0)))
  47. end
  48.  
  49. procedure defnon(sym)
  50.    if sym ? {
  51.       ="'" &
  52.       chars := cset(tab(-1)) &
  53.       ="'"
  54.       }
  55.    then return charset(chars)
  56.    else if sym ? {
  57.       ="?" &
  58.       name := tab(0)
  59.       }
  60.    then return query(name)
  61.    else return nonterm(sym)
  62. end
  63.  
  64. procedure error(line)
  65.    write("*** erroneous line:  ",line)
  66.    return
  67. end
  68.  
  69. procedure gener(goal)
  70.    local pending, genstr, symbol
  71.    repeat {
  72.       pending := [nonterm(goal)]
  73.       genstr := ""
  74.       while symbol := get(pending) do {
  75.          if \tswitch then write(&errout,genstr,symimage(symbol),listimage(pending))
  76.          case type(symbol) of {
  77.             "string":   genstr ||:= symbol
  78.             "charset":  genstr ||:= ?symbol.chars
  79.         "query":    {
  80.                writes("*** supply string for ",symbol.name,"  ")
  81.                genstr ||:= read() | {
  82.                   write(&errout,"*** no value for query to ",symbol.name)
  83.                   suspend genstr
  84.                   break next
  85.                   }
  86.                }
  87.             "nonterm":  {
  88.                pending := ?\defs[symbol.name] ||| pending | {
  89.                   write(&errout,"*** undefined nonterminal:  <",symbol.name,">")
  90.                   suspend genstr
  91.                   break next
  92.                   }
  93.                if *pending > \limit then {
  94.                   write(&errout,"*** excessive symbols remaining")
  95.                   suspend genstr
  96.                   break next
  97.                   }
  98.                }
  99.             }
  100.          }
  101.       suspend genstr
  102.       }
  103. end
  104.  
  105. procedure generate(line)
  106.    local goal, count
  107.    if line ? {
  108.       ="<" &
  109.       goal := tab(upto('>')) \ 1 &
  110.       move(1) &
  111.       count := (pos(0) & 1) | integer(tab(0))
  112.       }
  113.    then {
  114.       every write(gener(goal)) \ count
  115.       return
  116.       }
  117.    else fail
  118. end
  119.  
  120. procedure getrhs(a)
  121.    local rhs
  122.    rhs := ""
  123.    every rhs ||:= sform(!a) || "|"
  124.    return rhs[1:-1]
  125. end
  126.  
  127. procedure grammar(line)
  128.    local file, out
  129.    if line ? {
  130.       name := tab(find("->")) &
  131.       move(2) &
  132.       file := tab(0) &
  133.       out := if *file = 0 then &output else {
  134.          open(file,"w") | {
  135.             write(&errout,"*** cannot open ",file)
  136.             fail
  137.             }
  138.          }
  139.       }
  140.    then {
  141.       (*name = 0) | (name[1] == "<" & name[-1] == ">") | fail
  142.       pwrite(name,out)
  143.       if *file ~= 0 then close(out)
  144.       return
  145.       }
  146.    else fail
  147. end
  148.  
  149. procedure listimage(a)
  150.    local s, x
  151.    s := ""
  152.    every x := !a do
  153.       s ||:= symimage(x)
  154.    return s
  155. end
  156.  
  157. procedure alts(defn)
  158.    local alist
  159.    alist := []
  160.    defn ? while put(alist,syms(tab(many(~'|')))) do move(1)
  161.    return alist
  162. end
  163.  
  164. procedure prompter(line)
  165.    if line[1] == "=" then {
  166.       prompt := line[2:0]
  167.       return
  168.       }
  169. end
  170.  
  171. procedure pwrite(name,ofile)
  172.    local nt, a
  173.    static builtin
  174.    initial builtin := ["lb","rb","vb","nl","","&lcase","&ucase","&digit"]
  175.    if *name = 0 then {
  176.       a := sort(defs)
  177.       every nt := !a do {
  178.          if nt[1] == !builtin then next
  179.          write(ofile,"<",nt[1],">::=",getrhs(nt[2]))
  180.          }
  181.       }
  182.    else write(ofile,name,"::=",getrhs(\defs[name[2:-1]])) |
  183.       write("*** undefined nonterminal:  ",name)
  184. end
  185.  
  186. procedure sform(alt)
  187.    local s, x
  188.    s := ""
  189.    every x := !alt do
  190.       s ||:= case type(x) of {
  191.          "string":  x
  192.          "nonterm": "<" || x.name || ">"
  193.          "charset": "<'" || x.chars || "'>"
  194.          }
  195.    return s
  196. end
  197.  
  198. procedure source(line)
  199.    return line ? (="@" & push(ifile,in) & {
  200.       in := open(file := tab(0)) | {
  201.          write(&errout,"*** cannot open ",file)
  202.          fail
  203.          }
  204.       })
  205. end
  206.  
  207. procedure symimage(x)
  208.    return case type(x) of {
  209.       "string":   x
  210.       "nonterm":  "<" || x.name || ">"
  211.       "charset":  "<'" || x.chars || "'>"
  212.       }
  213. end
  214.  
  215. procedure syms(alt)
  216.    local slist
  217.    slist := []
  218.    alt ? while put(slist,tab(many(~'<')) |
  219.       defnon(2(="<",tab(upto('>')),move(1))))
  220.    return slist
  221. end
  222.  
  223.